/*     */ package com.zimbra.cs.service.formatter;
/*     */ 
/*     */ import com.google.common.base.Charsets;
/*     */ import com.google.common.base.Strings;
/*     */ import com.google.common.collect.ImmutableSet;
/*     */ import com.zimbra.common.localconfig.KnownKey;
/*     */ import com.zimbra.common.localconfig.LC;
/*     */ import com.zimbra.common.mime.MimeDetect;
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.util.ByteUtil;
/*     */ import com.zimbra.common.util.HttpUtil;
/*     */ import com.zimbra.common.util.HttpUtil.Browser;
/*     */ import com.zimbra.common.util.ImageUtil;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.LogFactory;
/*     */ import com.zimbra.common.util.StringUtil;
/*     */ import com.zimbra.cs.account.Account;
/*     */ import com.zimbra.cs.convert.ConversionUnsupportedException;
/*     */ import com.zimbra.cs.extension.ExtensionUtil;
/*     */ import com.zimbra.cs.html.BrowserDefang;
/*     */ import com.zimbra.cs.html.DefangFactory;
/*     */ import com.zimbra.cs.mailbox.CalendarItem;
/*     */ import com.zimbra.cs.mailbox.Contact;
/*     */ import com.zimbra.cs.mailbox.DeliveryOptions;
/*     */ import com.zimbra.cs.mailbox.Document;
/*     */ import com.zimbra.cs.mailbox.Folder;
/*     */ import com.zimbra.cs.mailbox.MailItem;
/*     */ import com.zimbra.cs.mailbox.MailItem.Type;
/*     */ import com.zimbra.cs.mailbox.MailServiceException;
/*     */ import com.zimbra.cs.mailbox.MailServiceException.NoSuchItemException;
/*     */ import com.zimbra.cs.mailbox.Mailbox;
/*     */ import com.zimbra.cs.mailbox.Message;
/*     */ import com.zimbra.cs.mime.MPartInfo;
/*     */ import com.zimbra.cs.mime.Mime;
/*     */ import com.zimbra.cs.mime.ParsedDocument;
/*     */ import com.zimbra.cs.mime.ParsedMessage;
/*     */ import com.zimbra.cs.service.UserServletContext;
/*     */ import com.zimbra.cs.service.UserServletException;
/*     */ import com.zimbra.cs.service.mail.UploadScanner;
/*     */ import com.zimbra.cs.service.mail.UploadScanner.Result;
/*     */ import com.zimbra.cs.service.util.ItemId;
/*     */ import com.zimbra.cs.servlet.ETagHeaderFilter;
/*     */ import com.zimbra.cs.store.Blob;
/*     */ import com.zimbra.cs.store.StoreManager;
/*     */ import java.awt.image.BufferedImage;
/*     */ import java.io.ByteArrayInputStream;
/*     */ import java.io.ByteArrayOutputStream;
/*     */ import java.io.IOException;
/*     */ import java.io.InputStream;
/*     */ import java.io.PrintWriter;
/*     */ import java.io.PushbackInputStream;
/*     */ import java.io.UnsupportedEncodingException;
/*     */ import java.nio.charset.Charset;
/*     */ import java.util.EnumSet;
/*     */ import java.util.List;
/*     */ import java.util.Map;
/*     */ import java.util.Set;
/*     */ import javax.imageio.ImageIO;
/*     */ import javax.imageio.ImageReader;
/*     */ import javax.imageio.ImageWriter;
/*     */ import javax.imageio.stream.MemoryCacheImageInputStream;
/*     */ import javax.imageio.stream.MemoryCacheImageOutputStream;
/*     */ import javax.mail.MessagingException;
/*     */ import javax.mail.internet.MimeMessage;
/*     */ import javax.mail.internet.MimePart;
/*     */ import javax.mail.internet.MimeUtility;
/*     */ import javax.servlet.RequestDispatcher;
/*     */ import javax.servlet.ServletException;
/*     */ import javax.servlet.http.HttpServletRequest;
/*     */ import javax.servlet.http.HttpServletResponse;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public final class NativeFormatter
/*     */   extends Formatter
/*     */ {
/*     */   private static final String CONVERSION_PATH = "/extension/convertd";
/*     */   public static final String ATTR_INPUTSTREAM = "inputstream";
/*     */   public static final String ATTR_MSGDIGEST = "msgdigest";
/*     */   public static final String ATTR_FILENAME = "filename";
/*     */   public static final String ATTR_CONTENTURL = "contenturl";
/*     */   public static final String ATTR_CONTENTTYPE = "contenttype";
/*     */   public static final String ATTR_CONTENTLENGTH = "contentlength";
/*  96 */   private static final Log log = LogFactory.getLog(NativeFormatter.class);
/*     */   
/*  98 */   private static final Set<String> SCRIPTABLE_CONTENT_TYPES = ImmutableSet.of("text/html", "application/xhtml+xml", "text/xml", "application/x-zimbra-doc", "application/x-zimbra-slides", "application/x-zimbra-xls", new String[] { "image/svg+xml", "application/xml" });
/*     */   
/*     */   private static final String HTML_VIEW = "html";
/*     */   
/*     */   private static final String TEXT_VIEW = "text";
/*     */   
/*     */   private static final int READ_AHEAD_BUFFER_SIZE = 256;
/*     */   
/*     */ 
/*     */   public FormatterFactory.FormatType getType()
/*     */   {
/* 109 */     return FormatterFactory.FormatType.HTML_CONVERTED;
/*     */   }
/*     */   
/*     */ 
/*     */   public Set<MailItem.Type> getDefaultSearchTypes()
/*     */   {
/* 115 */     return EnumSet.of(MailItem.Type.MESSAGE);
/*     */   }
/*     */   
/*     */   public void formatCallback(UserServletContext context) throws IOException, ServiceException, UserServletException, ServletException
/*     */   {
/*     */     try {
/* 121 */       sendZimbraHeaders(context, context.resp, context.target);
/* 122 */       HttpUtil.Browser browser = HttpUtil.guessBrowser(context.req);
/* 123 */       if (browser == HttpUtil.Browser.IE) {
/* 124 */         context.resp.addHeader("X-Content-Type-Options", "nosniff");
/*     */       }
/* 126 */       if ((context.target instanceof Message)) {
/* 127 */         handleMessage(context, (Message)context.target);
/* 128 */       } else if ((context.target instanceof CalendarItem))
/*     */       {
/* 130 */         CalendarItem calItem = (CalendarItem)context.target;
/* 131 */         if ((calItem.isPublic()) || (calItem.allowPrivateAccess(context.getAuthAccount(), context.isUsingAdminPrivileges())))
/*     */         {
/* 133 */           handleCalendarItem(context, calItem);
/*     */         } else {
/* 135 */           context.resp.sendError(403, "permission denied");
/*     */         }
/* 137 */       } else if ((context.target instanceof Document)) {
/* 138 */         handleDocument(context, (Document)context.target);
/* 139 */       } else if ((context.target instanceof Contact)) {
/* 140 */         handleContact(context, (Contact)context.target);
/*     */       } else {
/* 142 */         throw UserServletException.notImplemented("can only handle messages/appointments/tasks/documents");
/*     */       }
/*     */     } catch (MessagingException me) {
/* 145 */       throw ServiceException.FAILURE(me.getMessage(), me);
/*     */     }
/*     */   }
/*     */   
/*     */   private void handleMessage(UserServletContext context, Message msg) throws IOException, ServiceException, MessagingException, ServletException {
/* 150 */     if (context.hasBody()) {
/* 151 */       List<MPartInfo> parts = Mime.getParts(msg.getMimeMessage());
/* 152 */       MPartInfo body = Mime.getTextBody(parts, false);
/* 153 */       if (body != null) {
/* 154 */         handleMessagePart(context, body.getMimePart(), msg);
/*     */       } else {
/* 156 */         context.resp.sendError(400, "body not found");
/*     */       }
/* 158 */     } else if (context.hasPart()) {
/* 159 */       MimePart mp = getMimePart(msg, context.getPart());
/* 160 */       handleMessagePart(context, mp, msg);
/*     */     } else {
/* 162 */       context.resp.setContentType("text/plain");
/* 163 */       long size = msg.getSize();
/* 164 */       if (size > 0L)
/* 165 */         context.resp.setContentLength((int)size);
/* 166 */       InputStream is = msg.getContentStream();
/* 167 */       ByteUtil.copy(is, true, context.resp.getOutputStream(), false);
/*     */     }
/*     */   }
/*     */   
/*     */   private void handleCalendarItem(UserServletContext context, CalendarItem calItem) throws IOException, ServiceException, MessagingException, ServletException {
/* 172 */     if (context.hasPart()) { MimePart mp;
/*     */       MimePart mp;
/* 174 */       if (context.itemId.hasSubpart()) {
/* 175 */         MimeMessage mbp = calItem.getSubpartMessage(context.itemId.getSubpartId());
/* 176 */         mp = Mime.getMimePart(mbp, context.getPart());
/*     */       } else {
/* 178 */         mp = getMimePart(calItem, context.getPart());
/*     */       }
/* 180 */       handleMessagePart(context, mp, calItem);
/*     */     } else {
/* 182 */       context.resp.setContentType("text/plain");
/* 183 */       InputStream is = calItem.getRawMessage();
/* 184 */       if (is != null)
/* 185 */         ByteUtil.copy(is, true, context.resp.getOutputStream(), false);
/*     */     }
/*     */   }
/*     */   
/*     */   private void handleContact(UserServletContext context, Contact con) throws IOException, ServiceException, MessagingException, ServletException {
/* 190 */     if (!con.hasAttachment()) {
/* 191 */       context.resp.sendError(400, "body not found");
/* 192 */     } else if (context.hasPart()) {
/* 193 */       MimePart mp = Mime.getMimePart(con.getMimeMessage(false), context.getPart());
/* 194 */       handleMessagePart(context, mp, con);
/*     */     } else {
/* 196 */       context.resp.setContentType("text/plain");
/* 197 */       InputStream is = new ByteArrayInputStream(con.getContent());
/* 198 */       ByteUtil.copy(is, true, context.resp.getOutputStream(), false);
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */   private void handleMessagePart(UserServletContext context, MimePart mp, MailItem item)
/*     */     throws IOException, MessagingException, ServletException
/*     */   {
/* 206 */     if (mp == null) {
/* 207 */       context.resp.sendError(400, "part not found");
/*     */     } else {
/* 209 */       String contentType = mp.getContentType();
/* 210 */       String shortContentType = Mime.getContentType(mp);
/*     */       
/* 212 */       if (contentType == null) {
/* 213 */         contentType = "text/plain";
/* 214 */       } else if (shortContentType.equalsIgnoreCase("application/octet-stream")) {
/* 215 */         if ((contentType = MimeDetect.getMimeDetect().detect(Mime.getFilename(mp), mp.getInputStream())) == null) {
/* 216 */           contentType = "application/octet-stream";
/*     */         } else {
/* 218 */           shortContentType = contentType;
/*     */         }
/*     */       }
/* 221 */       contentType = contentType.replace('\r', ' ').replace('\n', ' ');
/*     */       
/*     */ 
/* 224 */       HttpUtil.Browser browser = HttpUtil.guessBrowser(context.req);
/* 225 */       if ((browser == HttpUtil.Browser.IE) && (contentType.length() > 80)) {
/* 226 */         contentType = shortContentType;
/*     */       }
/*     */       
/* 229 */       boolean simpleText = (context.hasView()) && (context.getView().equals("text")) && ("message/rfc822".equals(contentType));
/*     */       
/* 231 */       if (simpleText) {
/* 232 */         contentType = "text/plain";
/*     */       }
/* 234 */       boolean html = (checkGlobalOverride("zimbraAttachmentsViewInHtmlOnly", context.getAuthAccount())) || ((context.hasView()) && (context.getView().equals("html")));
/*     */       
/* 236 */       InputStream in = null;
/*     */       try {
/* 238 */         if ((!html) || (ExtensionUtil.getExtension("convertd") == null) || (contentType.startsWith("text/html")) || (contentType.matches("image/.*")))
/*     */         {
/* 240 */           byte[] data = null;
/*     */           
/*     */ 
/*     */ 
/* 244 */           if (((context.hasMaxWidth()) || (context.hasMaxHeight())) && (Mime.getSize(mp) < LC.max_image_size_to_resize.intValue())) {
/*     */             try
/*     */             {
/* 247 */               data = getResizedImageData(mp, context.getMaxWidth(), context.getMaxHeight());
/*     */             }
/*     */             catch (Exception e)
/*     */             {
/* 251 */               log.info("Unable to resize image.  Returning original content.", e);
/*     */             }
/*     */           }
/*     */           
/*     */           long size;
/*     */           long size;
/* 257 */           if (data != null) {
/* 258 */             in = new ByteArrayInputStream(data);
/* 259 */             size = data.length;
/*     */           } else {
/* 261 */             in = mp.getInputStream();
/* 262 */             String enc = mp.getEncoding();
/* 263 */             if (enc != null) {
/* 264 */               enc = enc.toLowerCase();
/*     */             }
/* 266 */             size = (enc == null) || (enc.equals("7bit")) || (enc.equals("8bit")) || (enc.equals("binary")) ? mp.getSize() : 0L;
/*     */           }
/* 268 */           String defaultCharset = context.targetAccount.getAttr("zimbraPrefMailDefaultCharset", null);
/* 269 */           if (simpleText) {
/* 270 */             sendbackBinaryData(context.req, context.resp, in, contentType, "inline", null, size, true);
/*     */           }
/*     */           else {
/* 273 */             sendbackOriginalDoc(in, contentType, defaultCharset, Mime.getFilename(mp), mp.getDescription(), size, context.req, context.resp);
/*     */           }
/*     */         }
/*     */         else {
/* 277 */           in = mp.getInputStream();
/* 278 */           handleConversion(context, in, Mime.getFilename(mp), contentType, item.getDigest(), mp.getSize());
/*     */         }
/*     */       } finally {
/* 281 */         ByteUtil.closeStream(in);
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   private static byte[] getResizedImageData(MimePart mp, Integer maxWidth, Integer maxHeight)
/*     */     throws IOException, MessagingException
/*     */   {
/* 294 */     ImageReader reader = null;
/* 295 */     ImageWriter writer = null;
/* 296 */     InputStream in = null;
/*     */     
/* 298 */     if (maxWidth == null) {
/* 299 */       maxWidth = Integer.valueOf(LC.max_image_size_to_resize.intValue());
/*     */     }
/* 301 */     if (maxHeight == null) {
/* 302 */       maxHeight = Integer.valueOf(LC.max_image_size_to_resize.intValue());
/*     */     }
/*     */     try
/*     */     {
/* 306 */       reader = ImageUtil.getImageReader(Mime.getContentType(mp), mp.getFileName());
/* 307 */       if (reader == null) {
/* 308 */         log.debug("No ImageReader available.");
/* 309 */         return null;
/*     */       }
/*     */       
/*     */ 
/* 313 */       in = mp.getInputStream();
/* 314 */       reader.setInput(new MemoryCacheImageInputStream(in));
/* 315 */       BufferedImage img = reader.read(0);
/* 316 */       int width = img.getWidth();int height = img.getHeight();
/*     */       byte[] arrayOfByte2;
/* 318 */       if ((width <= maxWidth.intValue()) && (height <= maxHeight.intValue())) {
/* 319 */         log.debug("Image %dx%d is less than max %dx%d.  Not resizing.", new Object[] { Integer.valueOf(width), Integer.valueOf(height), maxWidth, maxHeight });
/*     */         
/* 321 */         return null;
/*     */       }
/*     */       
/*     */ 
/* 325 */       writer = ImageIO.getImageWriter(reader);
/* 326 */       if (writer == null) {
/* 327 */         log.debug("No ImageWriter available.");
/* 328 */         return null;
/*     */       }
/*     */       
/* 331 */       double ratio = Math.min(maxWidth.intValue() / width, maxHeight.intValue() / height);
/*     */       
/*     */ 
/*     */ 
/* 335 */       width = (int)(width * ratio);
/* 336 */       height = (int)(height * ratio);
/*     */       
/* 338 */       BufferedImage small = ImageUtil.resize(img, width, height);
/* 339 */       ByteArrayOutputStream out = new ByteArrayOutputStream();
/* 340 */       writer.setOutput(new MemoryCacheImageOutputStream(out));
/* 341 */       writer.write(small);
/* 342 */       return out.toByteArray();
/*     */     } finally {
/* 344 */       ByteUtil.closeStream(in);
/* 345 */       if (reader != null) {
/* 346 */         reader.dispose();
/*     */       }
/* 348 */       if (writer != null) {
/* 349 */         writer.dispose();
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   private void handleDocument(UserServletContext context, Document doc)
/*     */     throws IOException, ServiceException, ServletException
/*     */   {
/* 357 */     String v = (String)context.params.get("ver");
/* 358 */     int version = v != null ? Integer.parseInt(v) : -1;
/* 359 */     String contentType = doc.getContentType();
/*     */     
/* 361 */     doc = version > 0 ? (Document)doc.getMailbox().getItemRevision(context.opContext, doc.getId(), doc.getType(), version) : doc;
/* 362 */     InputStream is = doc.getContentStream();
/* 363 */     if (("html".equals(context.getView())) && ((contentType == null) || (!contentType.startsWith("text/html")))) {
/* 364 */       if (ExtensionUtil.getExtension("convertd") != null)
/*     */       {
/* 366 */         handleConversion(context, is, doc.getName(), doc.getContentType(), doc.getDigest(), doc.getSize());
/*     */       }
/*     */       else {
/*     */         try
/*     */         {
/* 371 */           updateClient(context, new ConversionUnsupportedException(String.format("Native format cannot be displayed inline: %s", new Object[] { contentType })));
/*     */         } catch (UserServletException e) {
/* 373 */           throw new ServletException(e.getLocalizedMessage(), e);
/*     */         }
/*     */       }
/*     */     } else {
/* 377 */       String defaultCharset = context.targetAccount.getAttr("zimbraPrefMailDefaultCharset", null);
/* 378 */       boolean neuter = doc.getAccount().getBooleanAttr("zimbraNotebookSanitizeHtml", true);
/* 379 */       if (neuter) {
/* 380 */         sendbackOriginalDoc(is, contentType, defaultCharset, doc.getName(), null, doc.getSize(), context.req, context.resp);
/*     */       } else
/* 382 */         sendbackBinaryData(context.req, context.resp, is, contentType, null, doc.getName(), doc.getSize());
/*     */     }
/*     */   }
/*     */   
/*     */   private void handleConversion(UserServletContext ctxt, InputStream is, String filename, String ct, String digest, long length) throws IOException, ServletException {
/*     */     try {
/* 388 */       ctxt.req.setAttribute("inputstream", is);
/* 389 */       ctxt.req.setAttribute("msgdigest", digest);
/* 390 */       ctxt.req.setAttribute("filename", filename);
/* 391 */       ctxt.req.setAttribute("contenttype", ct);
/* 392 */       ctxt.req.setAttribute("contenturl", ctxt.req.getRequestURI());
/* 393 */       ctxt.req.setAttribute("contentlength", Long.valueOf(length));
/* 394 */       RequestDispatcher dispatcher = ctxt.req.getRequestDispatcher("/extension/convertd");
/* 395 */       dispatcher.forward(ctxt.req, ctxt.resp);
/*     */     } finally {
/* 397 */       ByteUtil.closeStream(is);
/*     */     }
/*     */   }
/*     */   
/*     */   public static MimePart getMimePart(CalendarItem calItem, String part) throws IOException, MessagingException, ServiceException {
/* 402 */     return Mime.getMimePart(calItem.getMimeMessage(), part);
/*     */   }
/*     */   
/*     */   public static MimePart getMimePart(Message msg, String part) throws IOException, MessagingException, ServiceException {
/* 406 */     return Mime.getMimePart(msg.getMimeMessage(), part);
/*     */   }
/*     */   
/*     */   public static void sendbackOriginalDoc(InputStream is, String contentType, String defaultCharset, String filename, String desc, HttpServletRequest req, HttpServletResponse resp) throws IOException
/*     */   {
/* 411 */     sendbackOriginalDoc(is, contentType, defaultCharset, filename, desc, 0L, req, resp);
/*     */   }
/*     */   
/*     */   private static void sendbackOriginalDoc(InputStream is, String contentType, String defaultCharset, String filename, String desc, long size, HttpServletRequest req, HttpServletResponse resp) throws IOException
/*     */   {
/* 416 */     String disp = req.getParameter("disp");
/* 417 */     disp = (disp == null) || (disp.toLowerCase().startsWith("i")) ? "inline" : "attachment";
/* 418 */     if ((desc != null) && (desc.length() <= 2048)) {
/* 419 */       if ((desc.contains(" ")) && ((!desc.startsWith("\"")) || (!desc.endsWith("\"")))) {
/* 420 */         desc = "\"" + desc.trim() + "\"";
/*     */       }
/* 422 */       resp.addHeader("Content-Description", desc);
/*     */     }
/*     */     
/* 425 */     if ((disp.equals("inline")) && (isScriptableContent(contentType))) {
/* 426 */       BrowserDefang defanger = DefangFactory.getDefanger(contentType);
/* 427 */       String content = defanger.defang(Mime.getTextReader(is, contentType, defaultCharset), true);
/* 428 */       resp.setContentType(contentType);
/* 429 */       String charset = Mime.getCharset(contentType);
/* 430 */       resp.setCharacterEncoding(Strings.isNullOrEmpty(charset) ? Charsets.UTF_8.name() : charset);
/* 431 */       if (!content.isEmpty()) {
/* 432 */         resp.setContentLength(content.getBytes().length);
/*     */       }
/* 434 */       resp.getWriter().write(content);
/*     */     }
/*     */     else {
/* 437 */       if (contentType.startsWith("application/x-shockwave-flash")) {
/* 438 */         disp = "attachment";
/*     */       }
/* 440 */       resp.setContentType(contentType);
/* 441 */       sendbackBinaryData(req, resp, is, contentType, disp, filename, size);
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */   public boolean supportsSave()
/*     */   {
/* 448 */     return true;
/*     */   }
/*     */   
/*     */ 
/*     */   public void saveCallback(UserServletContext context, String contentType, Folder folder, String filename)
/*     */     throws IOException, ServiceException, UserServletException
/*     */   {
/* 455 */     if (filename == null) {
/* 456 */       Mailbox mbox = folder.getMailbox();
/*     */       try {
/* 458 */         ParsedMessage pm = new ParsedMessage(context.getPostBody(), mbox.attachmentsIndexingEnabled());
/* 459 */         DeliveryOptions dopt = new DeliveryOptions().setFolderId(folder).setNoICal(true);
/* 460 */         mbox.addMessage(context.opContext, pm, dopt, null);
/* 461 */         return;
/*     */       } catch (ServiceException e) {
/* 463 */         throw new UserServletException(400, "error parsing message");
/*     */       }
/*     */     }
/*     */     
/* 467 */     InputStream is = context.getRequestInputStream();
/*     */     try {
/* 469 */       Blob blob = StoreManager.getInstance().storeIncoming(is);
/* 470 */       saveDocument(blob, context, contentType, folder, filename, is);
/*     */     } finally {
/* 472 */       is.close();
/*     */     }
/*     */   }
/*     */   
/*     */   private void saveDocument(Blob blob, UserServletContext context, String contentType, Folder folder, String filename, InputStream is)
/*     */     throws IOException, ServiceException, UserServletException
/*     */   {
/* 479 */     Mailbox mbox = folder.getMailbox();
/* 480 */     MailItem item = null;
/*     */     
/* 482 */     String creator = context.getAuthAccount() == null ? null : context.getAuthAccount().getName();
/* 483 */     ParsedDocument pd = null;
/*     */     try
/*     */     {
/* 486 */       if (contentType == null) {
/* 487 */         contentType = MimeDetect.getMimeDetect().detect(filename);
/* 488 */         if (contentType == null) {
/* 489 */           contentType = "application/octet-stream";
/*     */         }
/*     */       }
/* 492 */       pd = new ParsedDocument(blob, filename, contentType, System.currentTimeMillis(), creator, context.req.getHeader("X-Zimbra-Description"), true);
/*     */       
/*     */ 
/* 495 */       item = mbox.getItemByPath(context.opContext, filename, folder.getId());
/*     */       
/* 497 */       if (!(item instanceof Document)) {
/* 498 */         throw new UserServletException(400, "cannot overwrite existing object at that path");
/*     */       }
/*     */       
/* 501 */       StringBuffer info = new StringBuffer();
/* 502 */       UploadScanner.Result result = UploadScanner.acceptStream(is, info);
/* 503 */       if (result == UploadScanner.REJECT)
/* 504 */         throw MailServiceException.UPLOAD_REJECTED(filename, info.toString());
/* 505 */       if (result == UploadScanner.ERROR) {
/* 506 */         throw MailServiceException.SCAN_ERROR(filename);
/*     */       }
/* 508 */       item = mbox.addDocumentRevision(context.opContext, item.getId(), pd);
/*     */     } catch (MailServiceException.NoSuchItemException nsie) {
/* 510 */       item = mbox.createDocument(context.opContext, folder.getId(), pd, MailItem.Type.DOCUMENT, 0);
/*     */     }
/*     */     
/* 513 */     sendZimbraHeaders(context, context.resp, item);
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   private static long getContentLength(HttpServletRequest req)
/*     */   {
/* 520 */     String contentLengthStr = req.getHeader("Content-Length");
/* 521 */     return contentLengthStr != null ? Long.parseLong(contentLengthStr) : -1L;
/*     */   }
/*     */   
/*     */   public static void sendZimbraHeaders(UserServletContext context, HttpServletResponse resp, MailItem item) {
/* 525 */     if ((resp == null) || (item == null)) {
/* 526 */       return;
/*     */     }
/* 528 */     if (context.wantCustomHeaders) {
/* 529 */       resp.addHeader("X-Zimbra-ItemId", item.getId() + "");
/* 530 */       resp.addHeader("X-Zimbra-Version", item.getVersion() + "");
/* 531 */       resp.addHeader("X-Zimbra-Modified", item.getChangeDate() + "");
/* 532 */       resp.addHeader("X-Zimbra-Change", item.getModifiedSequence() + "");
/* 533 */       resp.addHeader("X-Zimbra-Revision", item.getSavedSequence() + "");
/* 534 */       resp.addHeader("X-Zimbra-ItemType", item.getType().toString());
/*     */       try {
/* 536 */         String val = item.getName();
/* 537 */         if (!StringUtil.isAsciiString(val)) {
/* 538 */           val = MimeUtility.encodeText(val, "utf-8", "B");
/*     */         }
/* 540 */         resp.addHeader("X-Zimbra-ItemName", val);
/* 541 */         val = item.getPath();
/* 542 */         if (!StringUtil.isAsciiString(val)) {
/* 543 */           val = MimeUtility.encodeText(val, "utf-8", "B");
/*     */         }
/* 545 */         resp.addHeader("X-Zimbra-ItemPath", val);
/*     */       }
/*     */       catch (UnsupportedEncodingException e1) {}catch (ServiceException e) {}
/*     */     }
/*     */     
/*     */ 
/*     */ 
/* 552 */     resp.addDateHeader("Last-Modified", item.getDate());
/*     */     
/* 554 */     resp.addHeader("ETag", String.valueOf(item.getSavedSequence()));
/* 555 */     resp.addHeader(ETagHeaderFilter.ZIMBRA_ETAG_HEADER, String.valueOf(item.getSavedSequence()));
/*     */   }
/*     */   
/*     */ 
/* 559 */   private static final byte[][] SCRIPT_PATTERN = { { 60, 115, 99, 114, 105, 112, 116 }, { 60, 83, 67, 82, 73, 80, 84 } };
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */   public static void sendbackBinaryData(HttpServletRequest req, HttpServletResponse resp, InputStream in, String contentType, String disposition, String filename, long size)
/*     */     throws IOException
/*     */   {
/* 567 */     sendbackBinaryData(req, resp, in, contentType, disposition, filename, size, false);
/*     */   }
/*     */   
/*     */ 
/*     */   public static void sendbackBinaryData(HttpServletRequest req, HttpServletResponse resp, InputStream in, String contentType, String disposition, String filename, long size, boolean ignoreContentDisposition)
/*     */     throws IOException
/*     */   {
/* 574 */     resp.setContentType(contentType);
/* 575 */     if (disposition == null) {
/* 576 */       String disp = req.getParameter("disp");
/* 577 */       disposition = (disp == null) || (disp.toLowerCase().startsWith("i")) ? "inline" : "attachment";
/*     */     }
/* 579 */     PushbackInputStream pis = new PushbackInputStream(in, 256);
/* 580 */     boolean isSafe = false;
/* 581 */     HttpUtil.Browser browser = HttpUtil.guessBrowser(req);
/* 582 */     if (browser != HttpUtil.Browser.IE) {
/* 583 */       isSafe = true;
/* 584 */     } else if (disposition.equals("attachment")) {
/* 585 */       isSafe = true;
/* 586 */       if (isScriptableContent(contentType)) {
/* 587 */         resp.addHeader("X-Download-Options", "noopen");
/*     */       }
/*     */     }
/*     */     
/* 591 */     if (!isSafe) {
/* 592 */       byte[] buf = new byte['Ā'];
/* 593 */       int bytesRead = pis.read(buf, 0, 256);
/*     */       
/* 595 */       for (int i = 0; i < bytesRead; i++) {
/* 596 */         if ((buf[i] == SCRIPT_PATTERN[0][0]) || (buf[i] == SCRIPT_PATTERN[1][0])) {
/* 597 */           boolean hasScript = true;
/* 598 */           for (int pos = 1; (pos < 7) && (i + pos < bytesRead); pos++) {
/* 599 */             if ((buf[(i + pos)] != SCRIPT_PATTERN[0][pos]) && (buf[(i + pos)] != SCRIPT_PATTERN[1][pos]))
/*     */             {
/* 601 */               hasScript = false;
/* 602 */               break;
/*     */             }
/*     */           }
/* 605 */           if (hasScript) {
/* 606 */             resp.addHeader("Cache-Control", "no-transform");
/* 607 */             disposition = "attachment";
/* 608 */             break;
/*     */           }
/*     */         }
/*     */       }
/* 612 */       if (bytesRead > 0)
/* 613 */         pis.unread(buf, 0, bytesRead);
/*     */     }
/* 615 */     if (!ignoreContentDisposition) {
/* 616 */       String cd = HttpUtil.createContentDisposition(req, disposition, filename == null ? "unknown" : filename);
/* 617 */       resp.addHeader("Content-Disposition", cd);
/*     */     }
/* 619 */     if (size > 0L)
/* 620 */       resp.setContentLength((int)size);
/* 621 */     ByteUtil.copy(pis, true, resp.getOutputStream(), false);
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   private static boolean isScriptableContent(String contentType)
/*     */   {
/* 630 */     if (Strings.isNullOrEmpty(contentType)) {
/* 631 */       return false;
/*     */     }
/* 633 */     contentType = Mime.getContentType(contentType).toLowerCase();
/*     */     
/* 635 */     return SCRIPTABLE_CONTENT_TYPES.contains(contentType);
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/service/formatter/NativeFormatter.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */